package br.com.farmabid.login;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.ResourceBundle;

import javax.inject.Inject;

import org.apache.commons.codec.binary.Base64;

import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.view.Results;
import br.com.farmabid.cadastro.Farmacia;
import br.com.farmabid.component.AcessSession;
import br.com.farmabid.component.PasswordEncryptionService;
import br.com.farmabid.component.RandomAlphaNumeric;
import br.com.farmabid.component.StringUteis;
import br.com.farmabid.controller.BasicController;
import br.com.farmabid.controller.HomeController;
import br.com.farmabid.email.EmailDAO;
import br.com.farmabid.usuario.Usuario;
import br.com.farmabid.usuario.UsuarioDAO;

@Controller
public class LoginController extends BasicController {
	@Inject private UsuarioDAO usuarioDAO;
	@Inject private AcessSession session;
	@Inject private EmailDAO emailDAO;

	public LoginController(Result result, ResourceBundle bundle,
			UsuarioDAO usuarioDAO, AcessSession session) {
		this.result = result;
		this.bundle = bundle;
		this.usuarioDAO = usuarioDAO;
		this.session = session;
	}
	
	public LoginController(){}

	@Path(value = "/login/entrar")
	@Post
	public void entrar(Usuario usuario) {
		if(usuario != null){
			if(StringUteis.isEmpty(usuario.getEmail())){
    			mensagemErro("erro.email.usuario.obrigatorio");
    		}
    		if(StringUteis.isEmpty(usuario.getSenha())){
    			mensagemErro("erro.senha.usuario.obrigatorio");
    		}
    		if(resultPossui(ERROR) && resultPossuiConteudo(ERROR)){ redirect(); return;}
			Usuario temp = usuarioDAO.recuperaUsuariosPorEmail(usuario.getEmail());
			if(temp != null){
				if(temp.getTentativas() == 5){
					LocalDateTime fromDateTime = LocalDateTime.ofInstant(temp.getDataBloqueio().toInstant(), ZoneId.systemDefault());
					LocalDateTime toDateTime = LocalDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault());
					LocalDateTime tempDateTime = LocalDateTime.from( fromDateTime );
					long minutes = tempDateTime.until( toDateTime, ChronoUnit.MINUTES);
					if(minutes < 60){
						long falta = 60 - minutes;
						mensagemErro("erro.bloqueio.usuario", falta);
						result.redirectTo(HomeController.class).login();
						return;
					}
				}
				PasswordEncryptionService pas = new PasswordEncryptionService();
				try {
					Boolean retorno = pas.authenticate(usuario.getSenha(), Base64.decodeBase64(temp.getSenha()), Base64.decodeBase64(temp.getChave()));
					if(retorno){
						session.setNome(temp.getNome());
						session.setUsuario(temp);
						if("F".equals(temp.getTipo().getSigla())){
							Farmacia farmacia = usuarioDAO.recuperaFarmaciaUsuario(temp);
							if(farmacia != null){
								session.setFarmacia(farmacia);
							}
						}
						LogAcesso log = new LogAcesso();
						log.setUsuario(temp);
						log.setDataHora(new Date());
						usuarioDAO.save(log);
						
						if(temp.getTentativas() == 5){
							temp.setDataBloqueio(null);
							temp.setTentativas(0);
							usuarioDAO.update(temp);
						}
						result.redirectTo(HomeController.class).index();
					} else {
						if(null != temp.getTentativas()){
							if(temp.getTentativas() < 5){
								temp.setTentativas(temp.getTentativas() + 1);
								if(temp.getTentativas() == 5){
									temp.setDataBloqueio(new Date());
									usuarioDAO.update(temp);
									mensagemErro("erro.bloqueio.usuario", "60");
									result.redirectTo(HomeController.class).login();
									return;
								}
							}
						} else {
							temp.setTentativas(1);
						}
						usuarioDAO.update(temp);
						mensagemErro("erro.usuario.nao.encontrado");
						result.redirectTo(HomeController.class).login();
					}
				} catch (Exception e) {
					mensagemErro("erro.usuario.nao.encontrado");
					result.redirectTo(HomeController.class).login();
				}
				
			} else {
				mensagemErro("erro.usuario.nao.encontrado");
				result.redirectTo(HomeController.class).login();
			}
		} else {
			mensagemErro("erro.ao.recuperar");
			result.redirectTo(HomeController.class).login();
		}
    }
	
	@Path(value = "/login/enviarNovaSenha")
	@Post
	public void enviarNovaSenha(String esqueciEmail){
		Usuario usuario = usuarioDAO.recuperaUsuarioPorEmail(esqueciEmail);
		String retorno = "false";
		if(usuario != null){
			char[] chares = RandomAlphaNumeric.generatePswd(8, 8, 1,1,1);
			String senhaNova = chares.toString();
			usuario.setSenha(senhaNova);
			geraChaveCriptografada(usuario);
			usuarioDAO.update(usuario);
			emailDAO.enviaNovaSenha(senhaNova, usuario);
			retorno = "true";
		}
		result.use(Results.json()).from(retorno).serialize();
	}
	
	private void geraChaveCriptografada(Usuario usuario) {
		PasswordEncryptionService pes = new PasswordEncryptionService();
		
		try {
			byte[] salt = pes.generateSalt();
			usuario.setChave(Base64.encodeBase64String(salt));
			usuario.setSenha(Base64.encodeBase64String(pes.getEncryptedPassword(usuario.getSenha(), salt)));
		} catch (Exception e) {
			mensagemErro("erro.ao.gravar");
		}
	}
	
	@Override
	protected void redirect() {}
	
}